package com.mhys.ynnz_ssm.business.sys.controller;

import com.mhys.ynnz_ssm.business.sys.dto.FileDO;
import com.mhys.ynnz_ssm.business.sys.service.FileService;
import com.mhys.ynnz_ssm.core.dto.MyPager;
import com.mhys.ynnz_ssm.core.dto.MyResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.UUID;

/**
 * 文件上传、下载控制器
 * 2024/6/13
 */
@Controller
@RequestMapping("/file")
@Slf4j
public class FileController {

    @Resource(name = "fileServiceImpl")
    private FileService fileService;

    // 服务器的文件保存目录：需要根据你自己的实现修改
    private final static String  SAVE_PATH = "D:\\uploadFiles";

    /**
     * 文件上传
     * @param file 前端传过来的文件对象
     * @param busDesc 文件使用在哪个场景的描述，如用户、商品
     * @return
     */
    @PostMapping("/upload")  // /flie/upload
    @ResponseBody
    public MyResult uploadFile(MultipartFile file,@RequestParam(required = false,defaultValue = "默认") String busDesc) {

        MyResult result = new MyResult();

        log.info("--文件上传:"+file.getOriginalFilename()+"--");

        try {

            // 2.获取文件名称  XX.XX.pdf
            String originalFilename = file.getOriginalFilename();

            // 3. 获取文件的类型
            String file_type = originalFilename.substring(originalFilename.lastIndexOf("."));

            // 生成一个随机的文件名
            String fileID = UUID.randomUUID().toString().replaceAll("-","");

            // 4. 创建一个File对象
            File newFile = new File(SAVE_PATH+"\\"+fileID+file_type);



            // 5.文件上传前保存上传的文件数据
            // 5.1 创建一个实体对象
            FileDO fileDO = new FileDO();
            fileDO.setFileID(fileID);
            fileDO.setFileName(originalFilename);
            fileDO.setFileType(file_type);
            fileDO.setFileSize(file.getSize()/1024);
            fileDO.setBusDesc(busDesc);
            fileDO.setSavePath(SAVE_PATH+"\\"+fileID+file_type);

            if(".png".equalsIgnoreCase(file_type)
                    ||".jpg".equalsIgnoreCase(file_type)
                    ||".jpeg".equalsIgnoreCase(file_type)
                    ||".gif".equalsIgnoreCase(file_type)
                    ||".bmp".equalsIgnoreCase(file_type)
                    ||".svg".equalsIgnoreCase(file_type)
                    ||".psd".equalsIgnoreCase(file_type)
                    ||".tiff".equalsIgnoreCase(file_type)){ // 如果是图片的话转一个base64
                InputStream inputStream = file.getInputStream();
                byte[] bytes = new byte[inputStream.available()];
                inputStream.read(bytes);
                String base64String = Base64.getEncoder().encodeToString(bytes);
                fileDO.setBase64Img(base64String);
            }

            // 6. 上传文件
            file.transferTo(newFile);

            // 6.1 进行数据库保存
            int i = fileService.addFile(fileDO);
            if(i>0){
                result.setMsg("文件上传成功！");
                result.setData(fileDO);
            }else{
                result.setMsg("文件上传成功,但数据库保存出错！");
                result.setCode(500);
            }

        } catch (Exception e) {
            e.printStackTrace();
            result.setCode(500);
            result.setMsg("文件上传出错！");
        }

        return result;
    }

    /**
     * servlet文件下载法
     * @param fileID 文件id
     * @param response 响应对象
     * @return
     */
    @GetMapping("/fileDownLoad")
    @ResponseBody
    public void fileDownLoad(String fileID, HttpServletResponse response){

        System.out.println("--文件下载："+fileID+"--");

        // 1. 根据文件id查询文件数据
        FileDO fileDO = fileService.getFileByID(fileID);

        if(fileDO == null){ //如果文件信息不存在则返回空
            return;
        }

        // 2.如果文件数据存在再进行下载
        // 2.1.设置响应头
        //描述是文件下载
        response.setHeader("Content-Type", "application/x-msdownload");
        //下载文件的名称
        response.setHeader("Content-Disposition", "attachment;filename="+this.toUTF8(fileDO.getFileName()));


        try {
            // 3. 读取目标位置文件
            FileInputStream fileInputStream = new FileInputStream(fileDO.getSavePath());

            // 4. 获取输入流的字节信息
            byte [] fileBytes = new byte[fileInputStream.available()];

            // 5. 读取文件信息
            fileInputStream.read(fileBytes); // 文件信息就写入到 fileBytes 数组中了
            fileInputStream.close();

            // 6. 将fileBytes 数组写出
            ServletOutputStream outputStream = response.getOutputStream();

            outputStream.write(fileBytes);
            outputStream.flush();
            outputStream.close();

        } catch (Exception e) {
        }
    }

    // 将字符串进行utf-8编解码
    private String toUTF8(String tarStr) {

        byte[] bytes = new byte[0];
        String s = null;
        try {
            bytes = tarStr.getBytes("UTF-8");
            s = new String(bytes, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            System.err.println("文件下载时：字符编码转换错误");
        }

        return s;
    }

    /**
     * 获取文件数据通过文件id
     * @param fileID 文件id
     * @return
     */
    @GetMapping("/getFileDataByID")
    @ResponseBody
    public MyResult getFileDataByID(String fileID){

        log.info("--获取文件数据通过文件id：fileID="+fileID);

        MyResult result = new MyResult();

        FileDO fileDO = fileService.getFileByID(fileID);

        if(fileDO!=null){
            result.setMsg("文件信息查询成功！");
            result.setData(fileDO);
        }else{
            result.setMsg("文件信息查询不到！");
            result.setCode(500);
        }

        return result;
    }

    /**
     * 文件信息分页列表
     * @param fileDO 查询条件
     * @param pager 分页条件
     * @return
     */
    @GetMapping("/getFilePages")
    @ResponseBody
    public MyResult getFilePages(FileDO fileDO, MyPager pager){

        log.info("--文件信息分页列表：fileDO："+fileDO+";pager:"+pager);

        MyResult result = new MyResult<>();

        MyPager<FileDO> pages =  fileService.getFilePages(fileDO,pager);

        result.setMsg("查询成功！");
        result.setData(pages);

        return result;
    }

    /**
     * 删除文件信息以及文件
     * @param fileID
     *        支持单行删除和多行删除，多行删除用“,”英文逗号分隔
     * @return
     */
    @DeleteMapping("/deleteFile")
    @ResponseBody
    public MyResult deleteFile(String fileID){
        log.info("--删除文件信息以及文件：fileID："+fileID);

        MyResult result = new MyResult<>();

        List<String> ids = Arrays.asList(fileID.split(","));

        int len = fileService.deleteFile(ids);

        if(len>0) {
            result.setMsg("删除成功！");
        }
        else{
            result.setMsg("删除失败！");
            result.setCode(500);
        }


        return result;
    }

}
